﻿using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading;

namespace SMSRouter
{
    //public enum messageSource { Inbox, Outbox, User, DB, SMS };
    public class Controller:IDisposable
    {
        SummaryView summaryView;
        public ConcurrentBag<Message> MessagesList = new ConcurrentBag<Message>();
        private Thread controllerThread;
        private static Mutex mut = new Mutex();
        private volatile bool _shouldStop;
        public DatabaseManager dbManager = new DatabaseManager();
        public SmsManager smsManager = new SmsManager();


        //private Thread summaryViewThread;
        public Controller(SummaryView sv)
        {
            summaryView = sv;
            controllerThread = new Thread(controllerThreadEnvelope);
            _shouldStop = false;
            controllerThread.IsBackground = true;
            controllerThread.Start();
        }

        public void AddNewMessage(Message newMessage)
        {
            MessagesList.Add(newMessage);
            dbManager.ProcessMessage(newMessage);
            Synchronize();
        }


        public void Synchronize()
        {
            mut.WaitOne();
            // Synchronize with DB
                List<Message> dbMessages = dbManager.GetMessages();
                // Clear MessagesList
                Message deletedMessage;
                while (MessagesList.TryTake(out deletedMessage)) ;

                // Insert data from the DB
                for (int i = 0; i < dbMessages.Count; i++)
                {
                    MessagesList.Add(dbMessages[i]);
                }
            // Export Inbox and Outbox to UI
            summaryView.ModifyInboxAndOutbox();
            // Send unsent Outbox messages using 3g Modem
            for (int i = 0; i < MessagesList.Count; i++)
            {
                Message mes = MessagesList.ElementAt(i);
                if (mes.folder == "Outbox")
                {
                    if (smsManager.SendMessage(mes))
                    {
                        MessagesList.ElementAt(i).folder = "Send";
                        dbManager.ProcessMessage(MessagesList.ElementAt(i));
                    }
                }
            }
            // Get new messages with 3G Modem
            List<Message> newMessages = smsManager.getIncomingMessages();
            int qty = newMessages.Count;
            int currentMes = 0;
            while (currentMes < qty)
            {
                foreach (Message mes in MessagesList)
                    if ((mes.timeStamp == newMessages[currentMes].timeStamp) &&
                        (mes.From == newMessages[currentMes].From) &&
                        (mes.To == newMessages[currentMes].To) &&
                        (mes.folder == newMessages[currentMes].folder) &&
                        (mes.text == newMessages[currentMes].text))
                    {
                        newMessages.RemoveAt(currentMes);
                        currentMes--;
                        qty--;
                    }
                currentMes++;
            }


            foreach (Message mes in newMessages)
            {
                MessagesList.Add(mes);
            }
            // Update DB model
            if (newMessages.Count > 0)
            {
                foreach (Message mes in newMessages)
                    dbManager.ProcessMessage(mes);
            }

            mut.ReleaseMutex();
        }

        public void controllerThreadEnvelope()
        {
            while (!_shouldStop)
            {
                Synchronize();
                Thread.Sleep(10000);
            }
        }
        public bool ConnectModem(string p_strPortName, int p_uBaudRate, int p_uDataBits, int p_uReadTimeout, int p_uWriteTimeout)
        {
            lock (smsManager)
            {
                return smsManager.ConnectModem(p_strPortName, p_uBaudRate, p_uDataBits, p_uReadTimeout, p_uWriteTimeout);
            }
        }
        public void DisconnectModem()
        {
            lock (smsManager)
            {
                smsManager.ClosePort();
            }
        }
        public bool ManagePinCode(string pinCode, bool enterNew = true)
        {
            lock (smsManager)
            {
                if (smsManager.modemOnline)
                {
                    bool res = false;
                    res = smsManager.CheckPinStatus();
                    if (enterNew && !res)
                        smsManager.EnterPinCode(pinCode);
                    return smsManager.CheckPinStatus();
                }
                else
                    return false;
            }
        }

        public void Dispose()
        {
            _shouldStop = false;
        }

    }
}
